Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 6b09c6b26295196d41b72d9e1e421e57e6e3ab87


Parents : cf0d64a
Author : Mark Qvist <mark@unsigned.io>
Date : 2025-11-06T17:07:00+01:00

Added voice call notifications

Changes

3 files changed, 83 insertions(+), 66 deletions(-)

M sbapp/main.py +5 -2

Diff

diff --git a/sbapp/main.py b/sbapp/main.py
index ef304dc6..643b9f1a 100644
--- a/sbapp/main.py
+++ b/sbapp/main.py
@@ -1274,8 +1274,11 @@ class SidebandApp(MDApp):
data = extras.getString("intent_action", "undefined")
if data.startswith("conversation."):
conv_hexhash = bytes.fromhex(data.replace("conversation.", ""))
- def cb(dt):
- self.open_conversation(conv_hexhash)
+ def cb(dt): self.open_conversation(conv_hexhash)
+ Clock.schedule_once(cb, 0.2)
+
+ elif data.startswith("incoming_call"):
+ def cb(dt): self.voice_action()
Clock.schedule_once(cb, 0.2)
except Exception as e:

diff --git a/sbapp/services/sidebandservice.py b/sbapp/services/sidebandservice.py
index 32650235..f52a8098 100644
--- a/sbapp/services/sidebandservice.py
+++ b/sbapp/services/sidebandservice.py
@@ -65,71 +65,83 @@ class SidebandService():
}
def android_notification(self, title="", content="", ticker="", group=None, context_id=None):
- if android_api_version < 26:
- return
- else:
- package_name = "io.unsigned.sideband"
-
- if not self.notification_service:
- self.notification_service = cast(NotificationManager, self.app_context.getSystemService(
- Context.NOTIFICATION_SERVICE
- ))
-
- channel_id = package_name
- group_id = ""
- if group != None:
- channel_id += "."+str(group)
- group_id += str(group)
- if context_id != None:
- channel_id += "."+str(context_id)
- group_id += "."+str(context_id)
-
- if not title or title == "":
- channel_name = "Sideband"
+ try:
+ if android_api_version < 26: return
else:
- channel_name = title
-
- self.notification_channel = NotificationChannel(channel_id, channel_name, NotificationManager.IMPORTANCE_DEFAULT)
- self.notification_channel.enableVibration(True)
- self.notification_channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), None)
- self.notification_channel.setShowBadge(True)
- self.notification_service.createNotificationChannel(self.notification_channel)
-
- notification = NotificationBuilder(self.app_context, channel_id)
- notification.setContentTitle(title)
- notification.setContentText(AndroidString(content))
- notification.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
-
- # if group != None:
- # notification.setGroup(group_id)
-
- if not self.notification_small_icon:
- # path = self.sideband.notification_icon
- path = self.sideband.notif_icon_black
- bitmap = BitmapFactory.decodeFile(path)
- self.notification_small_icon = Icon.createWithBitmap(bitmap)
-
- notification.setSmallIcon(self.notification_small_icon)
- # notification.setLargeIcon(self.notification_small_icon)
-
- # large_icon_path = self.sideband.icon
- # bitmap_icon = BitmapFactory.decodeFile(large_icon_path)
- # notification.setLargeIcon(bitmap_icon)
-
- notification_intent = Intent(self.app_context, python_act)
- notification_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
- notification_intent.setAction(Intent.ACTION_MAIN)
- notification_intent.addCategory(Intent.CATEGORY_LAUNCHER)
- if context_id != None:
- cstr = f"conversation.{context_id}"
- notification_intent.putExtra(JString("intent_action"), JString(cstr))
- self.notification_intent = PendingIntent.getActivity(self.app_context, 0, notification_intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)
-
- notification.setContentIntent(self.notification_intent)
- notification.setAutoCancel(True)
-
- built_notification = notification.build()
- self.notification_service.notify(0, built_notification)
+ package_name = "io.unsigned.sideband"
+ silent_contexts = ["incoming_call"]
+
+ if not self.notification_service:
+ self.notification_service = cast(NotificationManager, self.app_context.getSystemService(Context.NOTIFICATION_SERVICE))
+
+ channel_id = package_name
+ group_id = ""
+ if group != None:
+ channel_id += "."+str(group)
+ group_id += str(group)
+ if context_id != None:
+ channel_id += "."+str(context_id)
+ group_id += "."+str(context_id)
+
+ if not title or title == "": channel_name = "Sideband"
+ else: channel_name = title
+
+ if context_id in silent_contexts: silent = True
+ else: silent = False
+
+ self.notification_channel = NotificationChannel(channel_id, channel_name, NotificationManager.IMPORTANCE_DEFAULT)
+ self.notification_channel.enableVibration(True)
+ if not silent: self.notification_channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), None)
+ else: self.notification_channel.setSound(None, None)
+ self.notification_channel.setShowBadge(True)
+ self.notification_service.createNotificationChannel(self.notification_channel)
+
+ notification = NotificationBuilder(self.app_context, channel_id)
+ notification.setContentTitle(title)
+ notification.setContentText(AndroidString(content))
+
+ if not silent: notification.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
+ else: notification.setSound(None, None)
+
+ # if group != None:
+ # notification.setGroup(group_id)
+
+ if not self.notification_small_icon:
+ # path = self.sideband.notification_icon
+ path = self.sideband.notif_icon_black
+ bitmap = BitmapFactory.decodeFile(path)
+ self.notification_small_icon = Icon.createWithBitmap(bitmap)
+
+ notification.setSmallIcon(self.notification_small_icon)
+ # notification.setLargeIcon(self.notification_small_icon)
+
+ # large_icon_path = self.sideband.icon
+ # bitmap_icon = BitmapFactory.decodeFile(large_icon_path)
+ # notification.setLargeIcon(bitmap_icon)
+
+ notification_intent = Intent(self.app_context, python_act)
+ notification_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
+ notification_intent.setAction(Intent.ACTION_MAIN)
+ notification_intent.addCategory(Intent.CATEGORY_LAUNCHER)
+ if context_id != None:
+ if context_id == "incoming_call":
+ cstr = context_id
+ notification_intent.putExtra(JString("intent_action"), JString(cstr))
+ else:
+ cstr = f"conversation.{context_id}"
+ notification_intent.putExtra(JString("intent_action"), JString(cstr))
+
+ self.notification_intent = PendingIntent.getActivity(self.app_context, 0, notification_intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)
+
+ notification.setContentIntent(self.notification_intent)
+ notification.setAutoCancel(True)
+
+ built_notification = notification.build()
+ self.notification_service.notify(0, built_notification)
+
+ except Exception as e:
+ RNS.log(f"Error while creating notification: {e}", RNS.LOG_ERROR)
+ RNS.trace_exception(e)
def check_permission(self, permission):
if RNS.vendor.platformutils.is_android():

diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py
index 78825dd1..e0abe85b 100644
--- a/sbapp/sideband/core.py
+++ b/sbapp/sideband/core.py
@@ -5575,6 +5575,8 @@ class SidebandCore():
def incoming_call(self, remote_identity):
display_name = self.voice_display_name(remote_identity.hash)
self.setstate("voice.incoming_call", display_name)
+ if self.gui_foreground(): RNS.log("Squelching call notification since GUI is in foreground", RNS.LOG_DEBUG)
+ else: self.notify(title="Incoming voice call", content=f"From {display_name}", group="LXST.Telephony", context_id="incoming_call")
rns_config = """# This template is used to generate a
# running configuration for Sideband's


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────